﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using M3G;

namespace MyTestProject {
    public class TestAnimationController {
        [Fact]
        public void TestConstructor () {
            var ctrl = new AnimationController ();

            Assert.Equal (0, ctrl.ActiveIntervalStart);
            Assert.Equal (0, ctrl.ActiveIntervalEnd);
            Assert.Equal (1.0f, ctrl.Weight);
            Assert.Equal (1.0f, ctrl.Speed);
        }

        [Fact]
        public void TestSetActiveInterval () {
            var ctrl = new AnimationController ();
            ctrl.SetActiveInterval (10, 20);


            Assert.Equal (10, ctrl.ActiveIntervalStart);
            Assert.Equal (20, ctrl.ActiveIntervalEnd);
        }

        [Fact]
        public void TestIsActive () {
            var ctrl = new AnimationController ();

            // always active when ActiveInterval=(0,0)
            Assert.Equal (true, ctrl.Active (-999));

            ctrl.SetActiveInterval (10, 20);

            Assert.Equal (false, ctrl.Active (-999));
            Assert.Equal (true, ctrl.Active (15));
        }

        [Fact]
        public void TestSetWeight () {
            var ctrl = new AnimationController ();
            ctrl.Weight = 2.0f;

            Assert.Equal (2.0f, ctrl.Weight);
        }

        [Fact]
        public void TestSetPosition () {
            var ctr = new AnimationController ();
            ctr.SetPosition (0.0f, 100);

            Assert.Equal (0.0f, ctr.Position (100));
            Assert.Equal (100, ctr.WorldTime (0.0f));
        }

        /**
         * 再生スピードを変えたときにポッピングが起きないように
         * 現在時刻(world=100)に対するシーケンス時間(sequential=100)が
         * 前後(1)(2)で一致していることをチェックしている。
         * */
        [Fact]
        public void TestSpeed () {
            var ctrl = new AnimationController ();

            ctrl.SetPosition (10.0f, 10);

            Assert.Equal (100, ctrl.Position (100));  // (1)

            ctrl.SetSpeed (2.0f, 100);

            Assert.Equal (2.0f, ctrl.Speed);
            Assert.Equal (100, ctrl.Position (100)); // (2)
        }

        /**
         * シーケンス時間 <--> ワールド時間の計算式が正しい事を確認するテスト
         * */
        [Fact]
        public void TestGetSequenceTime () {

            var ctrl = new AnimationController ();

            ctrl.SetPosition (100.0f, 100);
            ctrl.SetSpeed (2.0f, 100);

            Assert.Equal (300.0f, ctrl.Position (200));
            Assert.Equal (150, ctrl.WorldTime (200.0f));
        }

        [Fact]
        public void TestGetDuration () {
            var keySeq1 = new KeyframeSequence (16, 3, KeyframeSequence.Step);
            var keySeq2 = new KeyframeSequence (16, 3, KeyframeSequence.Step);
            keySeq1.Duration = 100;
            keySeq2.Duration = 200;
            var color1 = new AnimationTrack (keySeq1, AnimationTrack.Color);
            var color2 = new AnimationTrack (keySeq2, AnimationTrack.Color);

            var ctrl = new AnimationController ();
            color1.SetController (ctrl);
            color2.SetController (ctrl);

            Assert.Equal (200, ctrl.Duration);
        }

        [Fact]
        public void TestDuplication () {
            var ctrl = new AnimationController ();
            ctrl.SetActiveInterval (1, 2);
            ctrl.SetPosition (10, 20);
            ctrl.SetSpeed (2, 20);
            ctrl.UserID = 100;

            var dup = (AnimationController)ctrl.Duplicate ();

            Assert.Equal (ctrl.ActiveIntervalStart, dup.ActiveIntervalStart);
            Assert.Equal (ctrl.ActiveIntervalEnd, dup.ActiveIntervalEnd);
            Assert.Equal (ctrl.Position(20), dup.Position (20));
            Assert.Equal (ctrl.Speed, dup.Speed);
            Assert.Equal (ctrl.UserID, ctrl.UserID);
        }
    }
}
